Introduction to Python

For Data Science

Autor: Kay Kleinvogel

Dies ist mein Lerndokument für Python.

Die Hauptsächliche Informationsquelle ist das EdX Programm: (https://courses.edx.org/courses/course-v1:Microsoft+DAT208x+3T2017/course/)

Lists

Eine Liste ist eine Sammlung von verschiedenen Werten welche unter einer Variable gespeichert werden. Eine liste wird wie folgt deklariert.


In [1]:
list = [1,2,3,4,5]
list


Out[1]:
[1, 2, 3, 4, 5]

Es können auch verschiedene Datentypen innerhalb einer Liste gepseichert werden. So können Strings, Integer und Booleans zusammen in einer Liste Auftreten. Des weiteren können andere Variabeln und auch andere Listen innerhalb einer Liste gespeichert werden. Listen werden meist genutzt, um verschiedene Datenreihen zu speichern, da es unhandlich wäre für jeden Wert eine eigene Variable zu erstellen. Nutzen wir zum Beispiel die Vermessung einer Familie. Wichtig für uns ist die Körpergröße der Person. Da wir aber nur aus den Daten nicht herausfinden, welcher Wert zu welcher Person gehört verbinden wir dies mit den Namen der Person.


In [2]:
family = [['Dad', 1.90],
          ['Mom', 1.75],
          ['Sis', 1.60]]
family


Out[2]:
[['Dad', 1.9], ['Mom', 1.75], ['Sis', 1.6]]

Um von einer Liste innerhalb einer anderen Liste einen Wert zu erhalten wird ein zweites Paar eckige Klammern genutzt. Möchten wir also zum Beispiel die Körpergröße von Mom erhalten nutzen wir folgenden Befehl.


In [3]:
family[1][1]


Out[3]:
1.75

Unterteilung von Listen

Wollen wir nun bestimmte Teile einer Liste erhalten, müssen wir diese weiter unterteilen. Jeder Wert einer Liste ist mit einen Index versehen, welcher bei 0 anfängt. Schauen wir uns unsere liste "list" an, so könnne wir folgende Werte zuweisen.

Index = Wert 0 = 1 1 = 2 2 = 3 3 = 4 4 = 5

Um nun einen spezifischen Wert dieser Liste zu nutzen müssen wir den entsprechenden Index in die eckigen Klammern eintragen. Möchten wir zum Beispiel den Wert 4 (Index 3) erhalten, würde der Code wie folgt aussehen.


In [4]:
list[3]


Out[4]:
4

Man kann auch einen negativen Index nutzen. Dabei wird von hinten geschaut welcher Wert auf dem Index liegt. Möchten wir also wieder den Wert 4 erhalten so ist dies der zweite Wert von hinten.


In [5]:
list[-2]


Out[5]:
4

Falls wir aber mehrere Teile einer Liste erhalten wollen können wir die Liste "zerschneiden"(Slices). Das Format würde wie folgt genutzt werden list[anfang:ende]. Wichtig hierbei ist, dass der erste Wert enthalten ist, das Ende aber nicht. Wollen wir also nun die Werte 2 bis 4 erhalten müssen wir vom Index 1 bis 3 ausgeben. Da der letzte Wert aber nicht enthalten ist sieht der Code folgendermaßen aus.


In [6]:
list[1:4]


Out[6]:
[2, 3, 4]

Wir können auch den Anfang oder das Ende weglassen. Falls der Anfang nicht genannt wird, startet die Liste beim Index 0. Analog dazu endet eine Liste ohne definiertes Ende mit dem letzen Index.


In [7]:
print(list[:4])
print(list[2:])


[1, 2, 3, 4]
[3, 4, 5]

Veränderung von Listen

Listen werden manchmal verändert. Dies geschieht, falls die Daten zum Beispiel nicht mehr aktuell sind. Schauen wir uns unsere Familienliste an so kann es sein das die Schwester in der letzten Zeit gewachsen ist. Hierfür schauen wir uns an welches Element wir verändern wollen. Da die Schwester das 3. Element ist erhält sie den Index 2, und wir wollen die Größe verändern (Index 1). Die eigentliche Veränderung des Wertes wird durch ein "=" realisiert. Wollen wir also nun die Schwester 10 cm größer machen.


In [8]:
family[2][1] = 1.70
family


Out[8]:
[['Dad', 1.9], ['Mom', 1.75], ['Sis', 1.7]]

Wollen wir nun Werte hinzufügen so ist dies auch möglich. So habe ich mich selber vergessen und versuche mag mich nun selber hinzufügen.


In [9]:
family = family + ['Me',1.90]
family


Out[9]:
[['Dad', 1.9], ['Mom', 1.75], ['Sis', 1.7], 'Me', 1.9]

Falls wir nun Elemente löschen möchten, können wir dies mit den del() Befehl erledigen. So habe ich für mich entschieden, dass ich doch nur die Daten der anderen in dieser Liste haben möchte. Daher lösche ich mich selber wieder aus der Liste heraus. Daher habe ich die letzen beiden Idizien der Liste.


In [10]:
del(family[-2:])
family


Out[10]:
[['Dad', 1.9], ['Mom', 1.75], ['Sis', 1.7]]

Funktionen

Funktionen sind wiederverwendbare Teile eines Codes, welche genutzt werden um spezifische Probleme zu lösen. Sie können Daten übergeben bekommen, und es können eigene Funktionen erstellt werden. Ein Beispiel für eine Funktion ist max(). Diese Funktion schaut auf eine Liste und gibt uns den maximalen Wert heraus.


In [11]:
max(list)


Out[11]:
5

Hier schaut die Funktion in die Liste "list" und gibt den größten Wert aus, welcher hier 5 ist. Genau so gibt es eine Funktion min() welche den minimalen Wert ausgibt. Falls wir Fragen zu einer Funktion haben können wir über den help() Befehl Informationen zu dieser bestimmten Funktion erhalten und die Dokumentation einsehen.


In [12]:
help(min)


Help on built-in function min in module builtins:

min(...)
    min(iterable, *[, default=obj, key=func]) -> value
    min(arg1, arg2, *args, *[, key=func]) -> value
    
    With a single iterable argument, return its smallest item. The
    default keyword-only argument specifies an object to return if
    the provided iterable is empty.
    With two or more arguments, return the smallest argument.


In [13]:
min(list)


Out[13]:
1

Die Funktion len() gibt uns die Möglichkeit die Anzahl an Elemente einer Liste herauszufinden.


In [14]:
help(len)


Help on built-in function len in module builtins:

len(obj, /)
    Return the number of items in a container.


In [15]:
len(family)


Out[15]:
3

Die Funktion sorted() sortiert die Werte einer Liste. Dies ist heilfreich, falls wir zum Beispiel 2 Listen addieren und diese Ergebnisse dann in einer geordneten Reihenfolge wiedergeben wollen. Die Ergebnisse können umgekehrt werden, dann werden die Ergebnisse von groß --> klein geordnet.


In [16]:
help(sorted)


Help on built-in function sorted in module builtins:

sorted(iterable, key=None, reverse=False)
    Return a new list containing all items from the iterable in ascending order.
    
    A custom key function can be supplied to customise the sort order, and the
    reverse flag can be set to request the result in descending order.


In [17]:
#Übung von EdX
# Create lists first and second
first = [11.25, 18.0, 20.0]
second = [10.75, 9.50]

# Paste together first and second: full
full = first + second

# Sort full in descending order: full_sorted
full_sorted=sorted(full, reverse = True)

# Print out full_sorted
print(full_sorted)


[20.0, 18.0, 11.25, 10.75, 9.5]

Wollen wir dies nun in der Reihenfolge von klein zu groß ausdrücken müssen wir nur das Argument reverse=True weglassen, da die Default Einstellung bei reverse=False liegt.


In [18]:
sorted(full)


Out[18]:
[9.5, 10.75, 11.25, 18.0, 20.0]

Methoden

Methoden sind wie Funktionen, nur das diese an spezifische Datentypen gebunden sind. So hat ein String andere Methoden, als ein Integer oder eine Liste. Für eine Liste haben wir unter anderem die beiden Methoden count index. Count gibt an wie oft ein bestimmter Wert in einer Liste ist, und index an welcher Stelle sich dieser befindet. Methoden werden mit einen Punkt an das Objekt angehangen. Als Beispiel schauen wir wie oft "18" in unsere 'full' Liste auftritt und an welcher Stelle.


In [19]:
print(full)
print(full.index(18))
print(full.count(18))


[11.25, 18.0, 20.0, 10.75, 9.5]
1
1

Methoden können auch das entsprechende Objekt verändern. So haben Listen die Methode .append() welche es uns ermöglicht Daten einer Liste hinzuzufügen. Möchte ich also doch wieder auf die Liste ist dies durch .append() möglich.


In [20]:
family.append('me') ; family.append(1.85)
print(family)


[['Dad', 1.9], ['Mom', 1.75], ['Sis', 1.7], 'me', 1.85]

Packages

Packages sind Pakete von Funktionen welche nicht in der eigentlichen Python Distribution vorhanden sind. Diese können manuell installiert und importiert werden um spezifische Probleme zu lösen. Sie werden mit dem Import Befehl importiert.

NumPy

NumPy kurz für Numeric Python ist ein Packet, welches für viele mathematische Zusammenhänge genutzt wird. Ein Vorteil dieses Paketes ist das Numpy.array() welches uns erlaubt Berechnungen über einen kompletten Datensatz zu erledigen. Hierfür nutzen wir 2 Listen für das Gewicht einer Person und ihrer Körpergröße und wandeln diese in numpy.arrays um.


In [21]:
import numpy as np
height=[1.73,1.68,1.71,1.89,1.79]
weight=[65.4,59.2,63.6,88.4,68.7]
np_height = np.array(height)
np_weight = np.array(weight)
print(np_height)
print(np_weight)


[ 1.73  1.68  1.71  1.89  1.79]
[ 65.4  59.2  63.6  88.4  68.7]

Nun veruchen wir den BMI zu berechnen. Dies wäre mit einer normalen Liste nicht möglich, da NumPy uns aber nun erlaubt Berechnungen mit ganzen Arrays anzustellen ist dies möglich. Hierbei wird die Berechnung von Zelle zu Zelle angewendenet.


In [22]:
bmi = np_weight / np_height**2
print(bmi)


[ 21.85171573  20.97505669  21.75028214  24.7473475   21.44127836]

Das Numpy.array ist nun ein eigener Datentyp wie String, Integer oder List. Die bedeutet auch dass dieser Typ nun eigene Methoden hat, und auch Operatoren sich unterschiedlich verhalten. Nehmen wir zum Beispiel "+". Bei einer normalen Liste würden beide Listen aneinander angefügt werden, aber bei einen Numpy.array werden beide Werte addiert.


In [23]:
print(full + full)
print(np.array(full)+np.array(full))


[11.25, 18.0, 20.0, 10.75, 9.5, 11.25, 18.0, 20.0, 10.75, 9.5]
[ 22.5  36.   40.   21.5  19. ]

Es können ähnliche Methoden zur Unterteilung eines Numpy.arrays genutzt werden wie für eine Liste. Um bestimmte Werte zu erhalten kann der Index angegeben werden.


In [24]:
np_full = np.array(full)
print(full)
print(np_full[1])


[11.25, 18.0, 20.0, 10.75, 9.5]
18.0

Des weiteren sind wir in der Lage bestimmte Werte herauszufinden. Dafür nutzen wir entsprechende Relativitätszeichen. Möchten wir zum Beispiel alle Werte über 11 im Array full finden können wir dies wie folgt erreichen.


In [25]:
print(np_full>11)


[ True  True  True False False]

Nun gibt uns NumPy einen Boolean für jedes Element des Arrays. Falls dieser Wert größer als 11 ist erhalten wir ein True, und für alle anderen Werte ein False. Damit können wir jetzt ein Subset erstellen und nur diese Werte in eine neue Liste speichern.


In [26]:
print(np_full[np_full>11])


[ 11.25  18.    20.  ]

2D Numpy Arrays

Die Listen und Arrays, welche wir bis jetzt behandelt hatten waren nur 1-dimensional. Numpy Arrays bestehen aber in n Dimensionen. Konvertieren wir daher unsere Daten in ein 2D Array. Um nun die "Form" dieses Arrays zu sehen können wir np.shape() nutzen. Dies gibt uns die Form im Format Höhe x Breite aus.


In [27]:
np_2d = np.array([[1.73,1.68,1.71,1.89,1.79],
                 [65.4,59.2,63.6,88.4,68.7]])
print(np_2d)
print(np_2d.shape)


[[  1.73   1.68   1.71   1.89   1.79]
 [ 65.4   59.2   63.6   88.4   68.7 ]]
(2, 5)

Wollen wir nun spezifische Werte auswählen, so ist dies genauso möglich wie in einer Liste. Wir nutzen dafür ein Komma in der eckigen Klammer. Der erste Wert gibt dabei die Reihe an und der zweite Wert die Spalte. Die Unterteilungsbefehle gelten hier auch. Wollen wir also zum Beispiel Höhe und Gewicht der 2. und 3. Person benötigen wir beide Reihen und die Spalten mit den Index 3 und 4.


In [28]:
print(np_2d[:,3:5])


[[  1.89   1.79]
 [ 88.4   68.7 ]]

Mit 2D Arrays ist es genauso möglich Berechnungen anzuführen, so kann ich zum Beispiel Zwei 2D-Arrays addieren oder multiplizieren je nach Bedarf.


In [29]:
print(np_2d+np_2d)


[[   3.46    3.36    3.42    3.78    3.58]
 [ 130.8   118.4   127.2   176.8   137.4 ]]
Grundlegende NumPy Statistik

Am Anfang sollten wir uns erst einmal einen groben Überblick über ein Datenset beschaffen. Hierfür hat NumPy Methoden für statistische Mittel.

np.mean() - Durschnitt

np.median() - Median

np.corrcoef() - Verhältnisskonstante

np.std() - Standardabweichung

sort() - Ordnen der Daten

Matplotlib

Packet für Datenvisualisierung


In [30]:
import matplotlib.pyplot as plt

Matplotlib ist in der Lage verschiedene Daten in Grafiken anzuzeigen. Möchten wir zum Beispiel die Einwohnerentwicklung der Welt zeigen, so ist dies mit 2 Listen möglich. Hierzu erstellen wir erst einmal die Listen "year" und "pop" wobei year die Jahresanzahl angibt, und pop die Population in Milliarden.


In [31]:
year = [1950, 1970, 1990, 2010]
pop = [2.519, 3.692, 5.263, 6.971]

Nun geben wir an, dass wir aus den beiden Listen einen Graphen erschaffen wollen. Hierfür nutzen wir pl.plot(x,y). Der erste Wert gibt dabei die x-Achse an und der zweite Wert die y-Achse. Möchten wir diesen Graphen nun sichtbar machen, so können wir dies mit plt.show() erreichen.


In [32]:
plot = plt.plot(year,pop)
plt.show(plot)


Der Scatter plot zeigt nur die Datenpunkte an, und verbindet diese nicht. Der Befehl dazu ist der gleiche nur dass wir plt.scatter(x,y) nutzen.


In [33]:
plot_scatter = plt.scatter(year,pop)
plt.show(plot_scatter)


Mann kann plt.xscale() und plt.yscale() nutzen um die Achseneinheiten zu verändern.

Histogramme (Balkendiagramm)

Sind eine gute Grundlage um sich einen Überblick über die Verteilung von Daten zu verschaffen. Werden mit plt.hist() erzeugt.


In [34]:
values = [0,0.6,1.4,1.6,2.2,2.5,2.6,3.2,3.5,3.9,4.3,6]
plt.hist(values,bins = 3)
plt.show()


Aufbereitung von Plots

Um Grafiken (Plots) anschaulich zu gestalten ist es wichtig sich von den obigen Darstellungen zu entfernen. Dafür sollten erst einmal die Achsen beschriftet werden.

Achsenbeschriftungen für die beiden Achsen erhalten wir durch folgende Befehle:

plt.xlabel('label')

plt.ylabel('label')

Um einen Titel einzufügen nutzen wir:

plt.title('title')

Des weiteren können wir noch die Schritte auf der Y-Achse verändern. Hierfür nutzen wir:

plt.yticks([1,2,3,4],
           ['0','1B','2B','3B','4B'])

Dafür haben wir auch noch die Schritte beschriftet um die Größe in Milliarden darzustellen.

Pandas

Pandas ist eine Python Bibliothek, welche in der Lage ist Daten aufzubereiten und auszuwerten. Hierfür nutzt Pandas CSV Dateien. Für weitere Infos zu Pandas bitte das Pandas Notebook aufsuchen.